﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using ConsoleRedirection;
using Team6_Algorithms.Filters;
using Team6_Algorithms.OCR;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Team6_Algorithms.Operations;
using Team6_Algorithms.AidingClasses;
using Team6_Algorithms.Binary;
using Team6_Algorithms.HighEnd;

//Written and rewritten by whole team
namespace VisionApplication
{
    public partial class MainForm : Form
    {

        /***********************************Global*************************************/
        string dirString;

       
        TextWriter _writer = null;

        List<VisionAlgorithm> WorkList = new List<VisionAlgorithm>(); 

        List<VisionAlgorithm> VAL = new List<VisionAlgorithm>();

        List<SingleCharacter> OcrList = new List<SingleCharacter>();
        List<TestsetCharacter> testSet = null;
        List<Bitmap> Characterlist = new List<Bitmap>();
        Awesome_O_CR awesomeOCR = new Awesome_O_CR();
        
        Stopwatch stopwatch = new Stopwatch();
        int[,] DirectionMap;


        public MainForm()
        {
            InitializeComponent();
            _writer = new TextBoxStreamWriter(txtConsole);
            // Redirect the out Console stream
            Console.SetOut(_writer);
            Console.Write("Welcome to the VisionLibrary tester\n");
            //add components to list

            VAL.Add(new BlobDetector("BlobDetector", null));
            VAL.Add(new NewMedian("Median", new string[] { "size", "image" }));
            VAL.Add(new SaltPepper("Salt Pepper noise", new string[] { "percentage", "image" }));
            VAL.Add(new PeriodicNoise("Periodic noise", new string[] { "width", "rows", "image" }));
            VAL.Add(new Masker("Mask", new string[] { "mask"}));
            VAL.Add(new Sobel("Sobel", new string[] { "max" }));
            VAL.Add(new LineDetection("Line Detection", new string[] { "max" }));
            VAL.Add(new DirectionDetection("Direction Detection", new string[] { "max", "treshold" }));
            VAL.Add(new GrayScale("GrayScalte", null));
            VAL.Add(new HSLSeparator("HSLseparator", new string[] { "HSL" }));
            VAL.Add(new CannyEdgeAlgo("Canny edge", null));
            VAL.Add(new KmeanAlgorithm("Kmeans", null));
            VAL.Add(new DetectLP1("DetectLP1", new string[] { "HSL" }));
            VAL.Add(new CannyAlgo("Detect LP Canny", new string[] {"size"}));


            foreach (VisionAlgorithm VA in VAL)
            {
                ListViewItem LVI = new ListViewItem(VA.Name);
                LVI.Tag = VA;
                AlgoList.Items.Add(LVI);
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = "Pictures\\";
            openFileDialog.FileName = "";
            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                String filename = openFileDialog.FileName;
                srcPictureBox.Image = Image.FromFile(filename);
                Console.Write("Picture has been opened\n");
                
            }
        }

        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void srcPictureBox_DoubleClick(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = "Pictures\\";
            openFileDialog.FileName = "";
            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                String filename = openFileDialog.FileName;
                srcPictureBox.Image = Image.FromFile(filename);
            }
        }

        private void result1PictureBox_DoubleClick(object sender, EventArgs e)
        {
            if (result1PictureBox.Image != null)
            {
                Form ipForm = new ImagePreviewForm(new Bitmap(result1PictureBox.Image));
                ipForm.Show();
            }

        }

        private void result2PictureBox_DoubleClick(object sender, EventArgs e)
        {
            if (result1PictureBox.Image != null)
            {
               // Form ipForm = new ImagePreviewForm(new Bitmap(result2PictureBox.Image));
              //  ipForm.Show();
            }
        }

        private void addButton_Click(object sender, EventArgs e)
        {
            
            if (AlgoList.SelectedItems.Count > 0)
            {
                ListViewItem LVI = (ListViewItem) AlgoList.SelectedItems[0].Clone();

                //Type cur = (Type) LVI.Tag.GetType();
                dynamic VA = LVI.Tag;
                
                string [] requiredList = new string[VA.settings.requiredList.Count];

                for (int i = 0; i < VA.settings.requiredList.Count; i++)
                {
                    requiredList[i] = VA.settings.requiredList[i];
                }

                SettingsForm sf = new SettingsForm(requiredList);

                if (sf.ShowDialog() == DialogResult.OK)
                {
                    Settings s = sf.settings.Clone();

                    VA._settings = s;

                    LVI.Tag = VA.Clone();

                    LVI.SubItems.Add(s.ToString());

                    TodoList.Items.Add(LVI);

                }
            }
        }

        private void deleteButton_Click(object sender, EventArgs e)
        {
            try
            {
                TodoList.Items.Remove(TodoList.SelectedItems[0]);
            }
            catch
            {
                MessageBox.Show("Please select something to remove.");
            }
        }

        private void runButton_Click(object sender, EventArgs e)
        {
            result1PictureBox.Image = srcPictureBox.Image;
            foreach (ListViewItem lvi in TodoList.Items)
            {
                dynamic VA = (VisionAlgorithm)lvi.Tag;
                    
                    Console.WriteLine("Started " + VA.settings.ToString());
                    stopwatch.Start();
                    if (VA.GetType().ToString() == "VisionApplication.ColorDirections")
                    {
                        result1PictureBox.Image = VA.DoAlgorithm((Bitmap)result1PictureBox.Image, DirectionMap);
                    }
                    else
                    {

                        result1PictureBox.Image = VA.DoAlgorithm((Bitmap)result1PictureBox.Image, null);
                    }
            
                    stopwatch.Stop();
                   
                    if (VA.GetType().ToString() == "VisionApplication.DirectionDetection")
                    {
                        DirectionMap = VA.Directions;
                        Console.WriteLine("DirectionMap Algorithems Enabled");
                    }

                    
                    Console.WriteLine("Done after {0} ms", stopwatch.ElapsedMilliseconds, VA.settings.ToString());
                    stopwatch.Reset();
                    
                
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Stopwatch t = new Stopwatch();
            t.Start();
            Compare cmp = new Compare((Bitmap)srcPictureBox.Image, (Bitmap)result1PictureBox.Image, (Bitmap)result1PictureBox.Image);
            cmp.start();
            t.Stop();
            Console.WriteLine("Done after: " + t.ElapsedMilliseconds + " ms");
            t.Reset();
        }

        private void TodoList_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            if (TodoList.SelectedItems.Count > 0)
            {
                dynamic VA = TodoList.SelectedItems[0].Tag;
                if (VA.Image != null)
                {
                  //  StepPictureBox.Image = VA.Image;
                }
            }
            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OcrList.Clear();
            List<String> Images;
            DirectoryInfo Di;
            FolderBrowserDialog FBD = new FolderBrowserDialog();
            if (dirString == null)
            {
                if (FBD.ShowDialog() == DialogResult.OK)
                {

                    dirString = FBD.SelectedPath;

                }
                else
                {
                    return;
                }
            }
            Images = Directory.GetFiles(dirString, "*.*", SearchOption.AllDirectories).ToList();
            foreach (string @s in Images)
            {
                Di = new DirectoryInfo(@s);
                string name = s.Substring(dirString.Length + 1);

                OcrList.Add(new SingleCharacter((Bitmap) Image.FromFile(@s),name));
            
            }
           
         
            srcPictureBox.Image = OcrList[1].Image;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            SingleCharacter SG = new SingleCharacter((Bitmap) srcPictureBox.Image, "Geen idee");
            SingleCharacter temp = null;
            float scoreDiff =0;
            bool first = true;
            foreach (SingleCharacter s in OcrList)
            {
                if (s.Score == SG.Score)
                {
                    temp = s;
                    break;
                }
                else
                {
                    if (first == true)
                    {
                        scoreDiff = SG.compareScore(s.Score);
                        temp = s;
                        first = false;
                    }
                    else
                    {
                        float tempScoreDiff = SG.compareScore(s.Score);
                        if (tempScoreDiff < scoreDiff)
                        {
                            temp = s;
                            scoreDiff = tempScoreDiff;
                        }
                    }
                    
                }

            }

            result1PictureBox.Image = SG.Image;
          //  result2PictureBox.Image = temp.Image;
            Console.WriteLine("Letter Gevonden! Het is de letter: "+ temp.Character+ " Het bijbehorende plaatje = " + temp.Name);




            
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OcrList.ObjectToFile("TestData.VSD");
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OcrList = (List<SingleCharacter>)  OcrList.FileToObject("TestData.VSD");
        }

        
        private void button4_click(object sender, EventArgs e)
        {
            Bitmap sourceBitmap;
            Bitmap tempBitmap = null;
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = "Pictures\\";
            openFileDialog.FileName = "";
            
            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                String filename = openFileDialog.FileName;
                tempBitmap = (Bitmap)Image.FromFile(filename);
                result1PictureBox.Image = tempBitmap;
            }

            Stopwatch t = new Stopwatch();
            t.Start();
            
            sourceBitmap = (Bitmap)srcPictureBox.Image;

            //TemplateMatching tussen sourceImage en template image
            TemplateMatcher.readTemplate(tempBitmap);
           // result2PictureBox.Image = TemplateMatcher.matchTemplate(sourceBitmap);
            
            t.Stop();
            Console.WriteLine("Done after: " + t.ElapsedMilliseconds + " ms");
            t.Reset();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            Awesome_O_CR awesomeOCR = new Awesome_O_CR();

            List<Bitmap> ImageList = new List<Bitmap>();

            List<String> Images;
            DirectoryInfo Di;
            FolderBrowserDialog FBD = new FolderBrowserDialog();
            if (dirString == null)
            {
                if (FBD.ShowDialog() == DialogResult.OK)
                {

                    dirString = FBD.SelectedPath;

                }
                else
                {
                    return;
                }
            }
            Images = Directory.GetFiles(dirString, "*.*", SearchOption.AllDirectories).ToList();
            foreach (string @s in Images)
            {
                Di = new DirectoryInfo(@s);
                string name = s.Substring(dirString.Length + 1);

                Bitmap newBitmap = new Bitmap(Image.FromFile(@s));
                newBitmap.Tag = name;

                ImageList.Add(newBitmap);
            
            }
         
           // srcPictureBox.Image = ImageList[1];

            Bitmap b = new Bitmap((Bitmap)srcPictureBox.Image);

            Object[,] PixelPoints = Binaryze.MakeBinairy(b);

            testSet = awesomeOCR.readTestSet(ImageList);

            List<TestsetCharacter> finalSet =  awesomeOCR.doAlgorithm((Bitmap)srcPictureBox.Image, "xxx_%@#76", testSet);

            Console.WriteLine("aantal chars in finalsset " + finalSet.Count);

            foreach (TestsetCharacter t in finalSet)
            {
                Console.WriteLine(t.Name);
            }

            int Width = b.Width;
            int Height = b.Height;
            //vertical slice
            srcPictureBox.Image = DrawRectangles.drawRectangle(b, (PixelPoint)PixelPoints[(Width / 2) - 1, 0], (PixelPoint)PixelPoints[(Width / 2) + 1, Height - 1]);
            //horizontal slice 1/3
            srcPictureBox.Image = DrawRectangles.drawRectangle(b, (PixelPoint)PixelPoints[0, (Height / 3) - 1], (PixelPoint)PixelPoints[Width - 1, (Height / 3) + 1]);
            //horizontal slice 2/3
            srcPictureBox.Image = DrawRectangles.drawRectangle(b, (PixelPoint)PixelPoints[0, (Height - Height / 3) - 1], (PixelPoint)PixelPoints[Width - 1, (Height - Height / 3) + 1]);
            //TopMask
            srcPictureBox.Image = DrawRectangles.drawRectangle(b, (PixelPoint)PixelPoints[0,0], (PixelPoint)PixelPoints[Width - 1, Height / 4]);
            //Leftmask
            srcPictureBox.Image = DrawRectangles.drawRectangle(b, (PixelPoint)PixelPoints[0,0], (PixelPoint)PixelPoints[Width / 4, Height - 1]);
            //RightMask
            srcPictureBox.Image = DrawRectangles.drawRectangle(b, (PixelPoint)PixelPoints[Width - Width / 4, 0], (PixelPoint)PixelPoints[Width - 1, Height - 1]);
            //BottomMask
            srcPictureBox.Image = DrawRectangles.drawRectangle(b, (PixelPoint)PixelPoints[0, Height - Height / 4], (PixelPoint)PixelPoints[Width - 1, Height - 1]);

            srcPictureBox.Refresh();
        }

        private void readTestsetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
            
            List<Bitmap> ImageList = new List<Bitmap>();

            List<String> Images;
            DirectoryInfo Di;
            FolderBrowserDialog FBD = new FolderBrowserDialog();
            if (dirString == null)
            {
                if (FBD.ShowDialog() == DialogResult.OK)
                {

                    dirString = FBD.SelectedPath;

                }
                else
                {
                    return;
                }
            }
            Images = Directory.GetFiles(dirString, "*.*", SearchOption.AllDirectories).ToList();
            foreach (string @s in Images)
            {
                Di = new DirectoryInfo(@s);
                string name = s.Substring(dirString.Length + 1);

                Bitmap newBitmap = new Bitmap(Image.FromFile(@s));
                newBitmap = newBitmap.addWhiteEdge(5);
                newBitmap.Tag = name;
                

                ImageList.Add(newBitmap);

            }

            Bitmap b = new Bitmap((Bitmap)srcPictureBox.Image);

            Object[,] PixelPoints = Binaryze.MakeBinairy(b);

            testSet = awesomeOCR.readTestSet(ImageList);

        }

        private void saveTestsetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (testSet != null)
            {
                try
                {
                    testSet.ObjectToFile("TestSet.OCR");
                    Console.WriteLine("Save succesvol");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Save gefaald::::::\n" + ex);
                }
            }
            else
            {
                Console.WriteLine("Kan niet saven, TestSet is leeg");
            }

 
        }

        private void loadTestsetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                testSet = (List<TestsetCharacter>)testSet.FileToObject("TestSet.OCR");
                Console.WriteLine("Read succesvol " + testSet.Count + " letters ingelezen");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Read gefaald::::::\n" + ex);
            }
        }

        private void inputImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            List<TestsetCharacter> finalSet = awesomeOCR.doAlgorithm((Bitmap)srcPictureBox.Image, "xxx_%@#76", testSet);

            Console.WriteLine("aantal chars in finalsset " + finalSet.Count);

            foreach (TestsetCharacter t in finalSet)
            {
                Console.WriteLine(t.Character);
            }
            sw.Stop();
            
            Console.WriteLine("Time elapsed " +sw.ElapsedMilliseconds);
        }

        private void foundLettersToolStripMenuItem_Click(object sender, EventArgs e)
        {
            long i = 0;
            Stopwatch sw = new Stopwatch();
            sw.Start();                             //start and stoptime from stopwatch is measured so bare algorithm time can be displayed
            sw.Stop();
            i = sw.ElapsedMilliseconds;
            sw.Reset();
            
            sw.Start();
            List<Char> LPList = new List<char>();
            foreach (Bitmap b in Characterlist)
            {
                Bitmap b2 = b.addWhiteEdge(5);
                List<TestsetCharacter> finalSet = awesomeOCR.doAlgorithm(b2, "xxx_%@#76", testSet);
                if (finalSet.Count == 0)
                {
                    LPList.Add('?');
                }
                else
                {
                    LPList.Add(Convert.ToChar(finalSet[0].Character));
                }

            }
            sw.Stop();
            string s = ""+ LPList[0];
            s += LPList[1];
            s += "-" + LPList[2];
            s += LPList[3];
            if (Char.IsNumber(LPList[5]) != Char.IsNumber(LPList[4]))
            {
                s += LPList[4] + "-";
            }
            else
            {
                s += "-" + LPList[4];
            }

            s += LPList[5];
            Console.WriteLine("Het gevonden kenteken is : " + s);
            Console.WriteLine("Tijd: "+ (sw.ElapsedMilliseconds - i)); // start+stop time from stopwatch is substracted
        }

        private void inputImageSegmentationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            long i = 0;
            Stopwatch sw = new Stopwatch();
            sw.Start();                             //start and stoptime from stopwatch is measured so bare algorithm time can be displayed
            sw.Stop();
            i = sw.ElapsedMilliseconds;
            sw.Reset();

            sw.Start();

            List<Blob> blobbers = new List<Blob>();

            blobbers = BlobDetection.doAlgorithm(new Bitmap(srcPictureBox.Image));
            int resultCounter = 0;

            blobbers.Sort((x, y) => x.minx.CompareTo(y.minx));

            int pixels = srcPictureBox.Width * srcPictureBox.Height;
            result1PictureBox.Image = (Bitmap)srcPictureBox.Image.Clone();

            foreach (Blob b in blobbers)
            {
                if (b.amountOfPixels < pixels / 1150)
                    continue;
                if (b.maxx - b.minx < 10)
                    continue;
                if (!(Math.Abs(b.maxx - b.minx) > Math.Abs(b.maxy - b.miny)))
                {
                    PixelPoint tempx = new PixelPoint(b.minx,b.miny , 231, 0, 0, 0, null);
                    PixelPoint tempy = new PixelPoint(b.maxx,b.maxy, 231, 0, 0, 0, null);

                    
                    result1PictureBox.Image = DrawRectangles.drawRectangle((Bitmap)result1PictureBox.Image, tempx, tempy);

                    try
                    {
                        Bitmap temp = ((Bitmap)srcPictureBox.Image).crop(b.minx, b.maxx, b.miny, b.maxy);
                        Characterlist.Add(temp);
                        temp.Save("D://bitmapTestSetCharacters/kek" + resultCounter + ".bmp");
                        
                    }
                    catch (Exception)
                    {
                       Console.WriteLine("Alles gaat hier goed hoor *whistle whistle*");
                    }
                    resultCounter++;
                }
            }

            if (Characterlist.Count == 0)
            {

                foreach (Blob b in blobbers)
                {
                    if (b.amountOfPixels < pixels / 2500)
                        continue;
                    if (b.maxx - b.minx < 10)
                        continue;
                    if (!(Math.Abs(b.maxx - b.minx) > Math.Abs(b.maxy - b.miny)))
                    {
                        PixelPoint tempx = new PixelPoint(b.minx, b.miny, 231, 0, 0, 0, null);
                        PixelPoint tempy = new PixelPoint(b.maxx, b.maxy, 231, 0, 0, 0, null);

                        result1PictureBox.Image = DrawRectangles.drawRectangle((Bitmap)result1PictureBox.Image, tempx, tempy);

                        try
                        {
                            Bitmap temp = ((Bitmap)srcPictureBox.Image).crop(b.minx, b.maxx, b.miny, b.maxy);
                            Characterlist.Add(temp);
                            temp.Save("D://bitmapTestSetCharacters/kek" + resultCounter + ".bmp");

                        }
                        catch (Exception)
                        {
                            Console.WriteLine("Alles gaat hier goed hoor *whistle whistle*");
                        }
                        resultCounter++;
                    }
                }




            }

            Console.WriteLine("Aantal blobs: " + Characterlist.Count);

            
            List<Char> LPList = new List<char>();
            foreach (Bitmap b in Characterlist)
            {
                List<TestsetCharacter> finalSet = awesomeOCR.doAlgorithm(b, "xxx_%@#76", testSet);

                

                if (finalSet.Count == 0)
                {
                    LPList.Add('?');
                }
                else
                {
                    LPList.Add(Convert.ToChar(finalSet[0].Character));
                }

            }
            sw.Stop();
            try
            {

                string s = "" + LPList[0];
                s += LPList[1];
                s += "-" + LPList[2];
                s += LPList[3];
                if (Char.IsNumber(LPList[5]) != Char.IsNumber(LPList[4]))
                {
                    s += LPList[4] + "-";
                }
                else
                {
                    s += "-" + LPList[4];
                }

                s += LPList[5];

                Console.WriteLine("Het gevonden kenteken is : " + s);
                Console.WriteLine("Tijd: " + (sw.ElapsedMilliseconds - i)); // start+stop time from stopwatch is substracted

                s = "";
            }
            catch
            {
                Console.WriteLine("Dit kenteken is te lelijk om een fatsoenlijk kenteken uit te halen..");
                Console.WriteLine("Dit is natuurlijk de fout van andere groepen.");
                Console.WriteLine("Persoonlijk denken wij dat de rotatie en vervorming groep dit fout gedaan hebben.");



            }
            blobbers.Clear();
            Characterlist.Clear();
            GC.Collect();
        }

        private void binarybutton_Click(object sender, EventArgs e)
        {
            Bitmap b = ((Bitmap)srcPictureBox.Image);
            int[,] Points = new int[b.Width, b.Height];

            Points = Binaryze.MakeBinaryIntImageInverted(b);

            result1PictureBox.Image = Binaryze.PaintInvertedIntBinairy(b, Points);
        }

       
    }
}
